www.gusucode.com > 基于Visual C++高级界面特效制作百例源码程序 > 基于Visual C++高级界面特效制作百例源码程序/code/char26/appbar/AppBar.cpp
// AppBar.cpp: implementation of the CAppBar class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "AppBar.h" #include <windowsx.h> #include "utility.h" #include "defines.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CAppBar::CAppBar(HWND hWnd) { m_hWnd = hWnd; m_bAppRegistered = FALSE; m_pOptions = new OPTIONS; ASSERT (m_pOptions); } CAppBar::~CAppBar() { if (m_pOptions) { delete m_pOptions; m_pOptions = NULL; } } // // AppBar_Size -- Handles updating the appbar's size and position. // void CAppBar::Size() { RECT rc; APPBARDATA abd; POPTIONS pOpt; if (m_bAppRegistered) { pOpt = GetAppbarData (); abd.cbSize = sizeof(APPBARDATA); abd.hWnd = m_hWnd; GetWindowRect (m_hWnd, &rc); QuerySetPos (pOpt->uSide, &rc, &abd, TRUE); } } // // QueryPos -- Asks the system if the AppBar can occupy the rectangle specified // -- in lprc. The system will change the lprc rectangle to make // -- it a valid rectangle on the desktop. // void CAppBar::QueryPos(LPRECT lprc) { POPTIONS pOpt; pOpt = GetAppbarData (); APPBARDATA abd; int iWidth = 0; int iHeight = 0; // Fill out the APPBARDATA struct and save the edge we're moving to // in the appbar OPTIONS struct. abd.hWnd = m_hWnd; abd.cbSize = sizeof(APPBARDATA); abd.rc = *lprc; abd.uEdge = pOpt->uSide; // Calculate the part we want to occupy. We only figure out the top // and bottom coordinates if we're on the top or bottom of the screen. // Likewise for the left and right. We will always try to occupy the // full height or width of the screen edge. if ((ABE_LEFT == abd.uEdge) || (ABE_RIGHT == abd.uEdge)) { iWidth = pOpt->cxWidth; abd.rc.top = 0; abd.rc.bottom = GetSystemMetrics(SM_CYSCREEN); } else { iHeight = pOpt->cyHeight; abd.rc.left = 0; abd.rc.right = GetSystemMetrics(SM_CXSCREEN); } // Ask the system for the screen space SHAppBarMessage(ABM_QUERYPOS, &abd); // The system will return an approved position along the edge we're asking // for. However, if we can't get the exact position requested, the system // only updates the edge that's incorrect. For example, if we want to // attach to the bottom of the screen and the taskbar is already there, // we'll pass in a rect like 0, 964, 1280, 1024 and the system will return // 0, 964, 1280, 996. Since the appbar has to be above the taskbar, the // bottom of the rect was adjusted to 996. We need to adjust the opposite // edge of the rectangle to preserve the height we want. switch (abd.uEdge) { case ABE_LEFT: abd.rc.right = abd.rc.left + iWidth; break; case ABE_RIGHT: abd.rc.left = abd.rc.right - iWidth; break; case ABE_TOP: abd.rc.bottom = abd.rc.top + iHeight; break; case ABE_BOTTOM: abd.rc.top = abd.rc.bottom - iHeight; break; } *lprc = abd.rc; } // // QuerySetPos -- Asks the system if the appbar can move itself to a particular // -- side of the screen and then does move the appbar. // void CAppBar::QuerySetPos(UINT uEdge, LPRECT lprc, PAPPBARDATA pabd, BOOL bMove) { int iHeight = 0; int iWidth = 0; POPTIONS pOpt = GetAppbarData(); // Fill out the APPBARDATA struct and save the edge we're moving to // in the appbar OPTIONS struct. pabd->rc = *lprc; pabd->uEdge = uEdge; pOpt->uSide = uEdge; QueryPos(&(pabd->rc)); // Tell the system we're moving to this new approved position. SHAppBarMessage(ABM_SETPOS, pabd); if (bMove) { // Move the appbar window to the new position MoveWindow(m_hWnd, pabd->rc.left, pabd->rc.top, pabd->rc.right - pabd->rc.left, pabd->rc.bottom - pabd->rc.top, TRUE); } // Save the appbar rect. We use this later when we autohide. If we're // currently hidden, then don't mess with this. if (!pOpt->fAutoHide) { m_rcAppBar = pabd->rc; } } // // PosChanged -- The system has changed our position for some reason. We need // -- to recalculate the position on the screen we want to occupy // -- by determining how wide or thick we are and the update the // -- screen position. // void CAppBar::PosChanged (PAPPBARDATA pabd) { RECT rc; RECT rcWindow; int iHeight; int iWidth; POPTIONS pOpt = GetAppbarData (); // Start by getting the size of the screen. rc.top = 0; rc.left = 0; rc.right = GetSystemMetrics(SM_CXSCREEN); rc.bottom = GetSystemMetrics(SM_CYSCREEN); // Update the m_rcAppBar so when we slide (if hidden) we slide to the // right place. if (pOpt->fAutoHide) { m_rcAppBar = rc; switch (pOpt->uSide) { case ABE_TOP: m_rcAppBar.bottom = m_rcAppBar.top + m_dwHeight; break; case ABE_BOTTOM: m_rcAppBar.top = m_rcAppBar.bottom - m_dwHeight; break; case ABE_LEFT: m_rcAppBar.right = m_rcAppBar.left + m_dwWidth; break; case ABE_RIGHT: m_rcAppBar.left = m_rcAppBar.right - m_dwWidth; break; } } // Now get the current window rectangle and find the height and width GetWindowRect(pabd->hWnd, &rcWindow); iHeight = rcWindow.bottom - rcWindow.top; iWidth = rcWindow.right - rcWindow.left; // Depending on which side we're on, try to preserve the thickness of // the window switch (pOpt->uSide) { case ABE_TOP: rc.bottom = rc.top + iHeight; break; case ABE_BOTTOM: rc.top = rc.bottom - iHeight; break; case ABE_LEFT: rc.right = rc.left + iWidth; break; case ABE_RIGHT: rc.left = rc.right - iWidth; break; } // Move the appbar. QuerySetPos (pOpt->uSide, &rc, pabd, TRUE); } void CAppBar::AppBarCallback (UINT uMsg, WPARAM wParam, LPARAM lParam) { APPBARDATA abd; static HWND hwndZOrder = NULL; POPTIONS pOpt = GetAppbarData (); abd.cbSize = sizeof(abd); abd.hWnd = m_hWnd; switch (wParam) { // Notifies the appbar that the taskbar's autohide or always-on-top // state has changed. The appbar can use this to conform to the settings // of the system taskbar. case ABN_STATECHANGE: break; // Notifies the appbar when a full screen application is opening or // closing. When a full screen app is opening, the appbar must drop // to the bottom of the Z-Order. When the app is closing, we should // restore our Z-order position. case ABN_FULLSCREENAPP: if (lParam) { // A full screen app is opening. Move us to the bottom of the // Z-Order. // First get the window that we're underneath so we can correctly // restore our position hwndZOrder = GetWindow (m_hWnd, GW_HWNDPREV); // Now move ourselves to the bottom of the Z-Order SetWindowPos(m_hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } else { // The app is closing. Restore the Z-order SetWindowPos(m_hWnd, pOpt->fOnTop ? HWND_TOPMOST : hwndZOrder, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); hwndZOrder = NULL; } break; // Notifies the appbar when an event has occured that may effect the // appbar's size and position. These events include changes in the // taskbar's size, position, and visiblity as well as adding, removing, // or resizing another appbar on the same side of the screen. case ABN_POSCHANGED: // Update our position in response to the system change PosChanged (&abd); break; } } // // Register -- Registers the appbar with the system. // BOOL CAppBar::Register() { APPBARDATA abd; abd.cbSize = sizeof(APPBARDATA); abd.hWnd = m_hWnd; abd.uCallbackMessage = APPBAR_CALLBACK; m_bAppRegistered = SHAppBarMessage (ABM_NEW, &abd); return m_bAppRegistered; } BOOL CAppBar::UnRegister() { APPBARDATA abd; abd.cbSize = sizeof(APPBARDATA); abd.hWnd = m_hWnd; m_bAppRegistered = !SHAppBarMessage(ABM_REMOVE, &abd); return !m_bAppRegistered; } // // SetAutoHide -- Causes the appbar window to either auto hide or stop auto hiding. // BOOL CAppBar::SetAutoHide(BOOL bHide) { if (bHide) { return AutoHide (); } else { return NoAutoHide (); } } // // AutoHide -- Does the work of changing the appbar to autohide. We check // -- to see if we can autohide, and if so unregister and tell // -- the system we are autohiding. // BOOL CAppBar::AutoHide() { HWND hwndAutoHide; APPBARDATA abd; POPTIONS pOpt = GetAppbarData(); BOOL bSuccess; RECT rc; CString strMsg; abd.cbSize = sizeof(APPBARDATA); abd.hWnd = m_hWnd; abd.uEdge = pOpt->uSide; // First figure out if someone already has this side for // autohiding hwndAutoHide = (HWND) SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd); if (hwndAutoHide != NULL) { return FALSE; } // We can autohide on this edge. Set the autohide style. abd.lParam = TRUE; bSuccess = (BOOL) SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd); if (!bSuccess) { #ifdef LOG strMsg.LoadString (IDS_ERROR_AUTOHIDE); gLog.WriteError (strMsg); #endif return FALSE; } else { // Since we're allowed to autohide, we need to adjust our screen // rectangle to the autohidden position. This will allow the system // to resize the desktop. pOpt->fAutoHide = TRUE; m_dwWidth = pOpt->cxWidth; m_dwHeight = pOpt->cyHeight; rc = m_rcAppBar; switch (pOpt->uSide) { case ABE_TOP: rc.bottom = rc.top + 2; break; case ABE_BOTTOM: rc.top = rc.bottom - 2; break; case ABE_LEFT: rc.right = rc.left + 2; break; case ABE_RIGHT: rc.left = rc.right - 2; break; } QuerySetPos(pOpt->uSide, &rc, &abd, TRUE); } return TRUE; } BOOL CAppBar::NoAutoHide() { HWND hwndAutoHide; APPBARDATA abd; POPTIONS pOpt = GetAppbarData(); BOOL fSuccess; CString strMsg; abd.cbSize = sizeof(APPBARDATA); abd.hWnd = m_hWnd; abd.uEdge = pOpt->uSide; // First let's check to see if we're the appbar attached to the // side of the screen abd.uEdge = pOpt->uSide; hwndAutoHide = (HWND) SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd); if (hwndAutoHide != m_hWnd) { strMsg.Format ("%s", STR_ERROR_NOT_HIDDEN); TRACE (strMsg); return FALSE; } // We can autohide or stop autohide on this edge. Set the autohide style. abd.lParam = FALSE; fSuccess = (BOOL) SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd); if (!fSuccess) { strMsg.Format ("%s", STR_ERROR_SET_AUTOHIDE); TRACE (strMsg); return FALSE; } else { // Need to change the appbar to get the screen desktop space // back. Also need to reattach the appbar to that edge of the // screen. pOpt->fAutoHide = FALSE; pOpt->cxWidth = m_dwWidth; pOpt->cyHeight = m_dwHeight; SetSide (pOpt->uSide); } return (TRUE); } BOOL CAppBar::SetSide(UINT uSide) { APPBARDATA abd; RECT rc; POPTIONS pOpt = GetAppbarData(); BOOL fAutoHide = FALSE; // Calculate the size of the screen so we can occupy the full width or // height of the screen on the edge we request. rc.top = 0; rc.left = 0; rc.right = GetSystemMetrics(SM_CXSCREEN); rc.bottom = GetSystemMetrics(SM_CYSCREEN); // Fill out the APPBARDATA struct with the basic information abd.cbSize = sizeof(APPBARDATA); abd.hWnd = m_hWnd; // If the appbar is autohidden, turn that off so we can move the bar if (pOpt->fAutoHide) { fAutoHide = pOpt->fAutoHide; // Turn off the redrawing of the desktop while we move things around. // If you put any breakpoints in this area you will lock up the desktop // Since turning off the desktop repaints turns it off for all the apps // in the system SetWindowRedraw (GetDesktopWindow(), FALSE); SetAutoHide (FALSE); } // Adjust the rectangle to set our height or width depending on the // side we want. switch (uSide) { case ABE_TOP: rc.bottom = rc.top + pOpt->cyHeight; break; case ABE_BOTTOM: rc.top = rc.bottom - pOpt->cyHeight; break; case ABE_LEFT: rc.right = rc.left + pOpt->cxWidth; break; case ABE_RIGHT: rc.left = rc.right - pOpt->cxWidth; break; } // Move the appbar to the new screen space. QuerySetPos(uSide, &rc, &abd, TRUE); // If the appbar was hidden, rehide it now if (fAutoHide) { SetAutoHide (TRUE); SetWindowRedraw (GetDesktopWindow(), TRUE); RedrawWindow (GetDesktopWindow(), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); } return TRUE; } void CAppBar::SetAlwaysOnTop(BOOL bOnTop) { POPTIONS pOpt = GetAppbarData(); // Update the window position to HWND_TOPMOST if we're to be always // on top, or HWND_NOTOPMOST if we're not. SetWindowPos(m_hWnd, (bOnTop) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); // Store the setting in the appbar OPTIONS struct. pOpt->fOnTop = bOnTop; } void CAppBar::Hide() { POPTIONS pOpt = GetAppbarData (); RECT rc; // Don't want to hide if AutoHide not set if (!pOpt->fAutoHide) { return; } // Calculate a hidden rectangle to use rc = m_rcAppBar; switch (pOpt->uSide) { case ABE_TOP: rc.bottom = rc.top + 2; break; case ABE_BOTTOM: rc.top = rc.bottom - 2; break; case ABE_LEFT: rc.right = rc.left + 2; break; case ABE_RIGHT: rc.left = rc.right - 2; break; } pOpt->fHiding = TRUE; CUtility Util; Util.SlideWindow (m_hWnd, &rc); } void CAppBar::UnHide() { POPTIONS pOpt = GetAppbarData(); CUtility Util; Util.SlideWindow (m_hWnd, &m_rcAppBar); pOpt->fHiding = FALSE; SetAutoHideTimer (); } void CAppBar::SetAutoHideTimer() { POPTIONS pOpt = GetAppbarData(); if (pOpt->fAutoHide) { SetTimer (m_hWnd, IDT_AUTOHIDE, 500, NULL); } } void CAppBar::SetAutoUnhideTimer() { POPTIONS pOpt = GetAppbarData(); if (pOpt->fAutoHide && pOpt->fHiding) { SetTimer(m_hWnd, IDT_AUTOUNHIDE, 50, NULL); } } POPTIONS CAppBar::GetAppbarData() { return m_pOptions; } BOOL CAppBar::SetAppbarData (POPTIONS pOptions) { if (!m_pOptions) { return FALSE; } m_pOptions->fAutoHide = pOptions->fAutoHide; m_pOptions->fOnTop = pOptions->fOnTop; m_pOptions->fHiding = pOptions->fHiding; m_pOptions->uSide = pOptions->uSide; m_pOptions->cxWidth = pOptions->cxWidth; m_pOptions->cyHeight = pOptions->cyHeight; for (int idx=0; idx<4; idx++) { m_pOptions->rcEdges[idx] = pOptions->rcEdges[idx]; } return TRUE; }